using System;
using System.Text;
using AudioComponent;
using EntitiesAndGameState;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Services;
using Utilities.Menu.UIElements;
using WAG.Menu;
using WAG.Resources;

namespace WAG
{

  using Game = Microsoft.Xna.Framework.Game;

    public enum PlayState
    {
        Playing,
        Pause,
        Controls
    }

  /// <summary>
  /// La classe UIRenderer si occupa di disegnare l'interfaccia: punteggi, informazioni utili, bottoni (il pulsante "QUIT GAME") etc.
  /// UIRenderer utilizza il servizio di IStateProvider per conoscere punteggio, numero di vite residue del giocatore, etc.
  /// </summary>
  public class UIRenderer : Microsoft.Xna.Framework.DrawableGameComponent
  {
    Matrix screen_transform;
    SpriteBatch sprite_batch;
    SpriteFont title_font, arial14, menu_f;
    Texture2D white_pixel, pause_bg, ship_icon, life_bar;
    Button resume, quit_to_menu, controls;
    SoundEffect click;

    float alpha = 0.0f;
    Texture2D single_tap, double_tap, long_tap;
    SpriteFont font_32, font_16, font12;
    Button back;
    Button[] weapons, wtype;
    Box box;
    private Texture2D ui_dock;
    private Texture2D score_dock;
    private Rectangle pause_rect;
    private Texture2D bar_block;
    Vector2 box_dimension = new Vector2(170, 200);
    Vector2 initial_box_pos = new Vector2(-200, 545), final_box_pos = new Vector2(12, 545);    

    PlayState state;

    public UIRenderer(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      this.UpdateOrder = (int)ComponentOrders.UI;
      this.DrawOrder = (int)ComponentOrders.UI;

    }

    IStateProvider<BaseLevelStats> state_provider;
    CameraProvider camera;
    public override void Initialize()
    {
      state_provider = Game.Services.GetService(typeof(IStateProvider<BaseLevelStats>)) 
        as IStateProvider<BaseLevelStats>;
      (Game.Services.GetService(typeof(IInputManager)) as IInputManager).OnTap += new InputManager.Tap(on_tap);

      camera = Game.Services.GetService(typeof(CameraProvider)) as CameraProvider;
      //var player_ship_index = (int)state_provider.CurrentState.player.AsShip.ship_type;

      //if (mode == GameMode.Campaign)
      //    ships = Leaderboard.GetCampaignState().CampaignState.Ships[player_ship_index];
      //else
      //    ships = Leaderboard.GetCampaignState().Ships[player_ship_index];

      state = PlayState.Playing;

      base.Initialize();
    }

    protected override void Dispose(bool disposing)
    {
        Game.Services.RemoveService(typeof(IInputManager));

        base.Dispose(disposing);
    }

    protected override void LoadContent()
    {
        title_font = Game.Content.Load<SpriteFont>(@"fonts\OCRAExtended28");
        arial14 = Game.Content.Load<SpriteFont>(@"fonts\arial14ptx");
        menu_f = Game.Content.Load<SpriteFont>(@"fonts\OCRAExtended18");
        sprite_batch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
        screen_transform = Matrix.CreateScale(GraphicsDevice.Viewport.Width / SpaceBattleGame.DEFAULT_SCR_HEIGHT, GraphicsDevice.Viewport.Height / 800.0f, 1.0f);
        white_pixel = Game.Content.Load<Texture2D>(@"UI\whitepixel");        
        ship_icon = Game.Content.Load<Texture2D>(@"UI\ship_ico");
        pause_bg = Game.Content.Load<Texture2D>(@"UI\pause_menu");
        click = Game.Content.Load<SoundEffect>(@"Audio\Bip");
        ui_dock = Game.Content.Load<Texture2D>(@"UI\upper_dock");
        score_dock = Game.Content.Load<Texture2D>(@"UI\score_dock");
        menu_dock = Game.Content.Load<Texture2D>(@"UI\menu_dock");
        bar_block = Game.Content.Load<Texture2D>(@"UI\bar_block");
        life_bar = Game.Content.Load<Texture2D>(@"UI\life_bar");
        //yellow_glow = Game.Content.Load<Texture2D>(@"UI\WSelector\yellow_glow");
        //white_glow = Game.Content.Load<Texture2D>(@"UI\WSelector\white_glow");
        //f_weapon_circle = Game.Content.Load<Texture2D>(@"UI\WSelector\weapon_circle");
        //s_weapon_circle = Game.Content.Load<Texture2D>(@"UI\WSelector\b_weapon_circle");

        double_tap = Game.Content.Load<Texture2D>("Menu/double_tap");
        single_tap = Game.Content.Load<Texture2D>("Menu/single_tap");
        long_tap = Game.Content.Load<Texture2D>("Menu/long_tap");
        font_32 = Game.Content.Load<SpriteFont>("Fonts/OCRAExtended30");
        font_16 = Game.Content.Load<SpriteFont>("Fonts/OCRAExtended16");
        font12 = Game.Content.Load<SpriteFont>("Fonts/OCRAExtended12");

        //f_weapon_circle_pos = new Vector2(240.0f - f_weapon_circle.Width / 2.0f, 400 - f_weapon_circle.Height / 2.0f);
        //s_weapon_circle_pos = new Vector2(240.0f - s_weapon_circle.Width / 2.0f, 400 - s_weapon_circle.Height / 2.0f);
        //half_yglow_vec = new Vector2(yellow_glow.Width / 2.0f, yellow_glow.Height / 2.0f);
        score_dock_pos = new Vector2(480 - score_dock.Width, 800 - score_dock.Height);
        menu_pos = new Vector2(0, 800 - menu_dock.Height);

        //tap_text_pos = new Vector2(240 - menu_f.MeasureString(tap_text).X / 2.0f, 400 + s_weapon_circle.Height / 2.0f + 20);

        pause_rect = new Rectangle(0, 800 - menu_dock.Height, menu_dock.Width, menu_dock.Height);

        var resume_sm = menu_f.MeasureString(Strings.Resume); var x = 12 + CenterValue(box_dimension.X, resume_sm.X);
        resume = new Button { CollisionBox = new Rectangle((int)x - 10, 560, (int)resume_sm.X + 20, (int)resume_sm.Y + 20), Label = Strings.Resume, Position = new Vector2(x, 570) };
        var control_sm = menu_f.MeasureString(Strings.PauseMenu_Controls); x = 12 + CenterValue(box_dimension.X, control_sm.X);
        controls = new Button { CollisionBox = new Rectangle((int)x - 10, 620, (int)control_sm.X + 20, (int)control_sm.Y + 20), Label = Strings.PauseMenu_Controls, Position = new Vector2(x, 630) };
        var quit_sm = menu_f.MeasureString(Strings.Quit); x = 12 + CenterValue(box_dimension.X, quit_sm.X);
        quit_to_menu = new Button { CollisionBox = new Rectangle((int)x - 10, 680, (int)quit_sm.X + 20, (int)quit_sm.Y + 20), Label = Strings.Quit, Position = new Vector2(x, 690) };

        var back_sm = font_32.MeasureString(Strings.Back); x = CenterValue(480, back_sm.X);
        back = new Button { CollisionBox = new Rectangle((int)x - 10, 650, (int)back_sm.X + 20, (int)back_sm.Y + 20), Label = Strings.Back, Position = new Vector2(x, 660.0f) };

        box = new Box(new Texture2D[] { Game.Content.Load<Texture2D>("UI/pause_menu_border"), 
            Game.Content.Load<Texture2D>("UI/WhitePixel"), Game.Content.Load<Texture2D>("UI/pause_menu_border") }, 
            initial_box_pos, box_dimension, Color.Black, 0.7f);

        weapons = new Button[11];

        weapons[0] = new Button { CollisionBox = new Rectangle(278, 273, 94, 86), Label = "", Position = new Vector2(314, 300), Pressed = false };
        weapons[1] = new Button { CollisionBox = new Rectangle(310, 412, 94, 86), Label = "", Position = new Vector2(345, 455), Pressed = false };
        weapons[2] = new Button { CollisionBox = new Rectangle(195, 488, 94, 86), Label = "", Position = new Vector2(240, 519), Pressed = false };
        weapons[3] = new Button { CollisionBox = new Rectangle(101, 409, 94, 86), Label = "", Position = new Vector2(126, 449), Pressed = false };
        weapons[4] = new Button { CollisionBox = new Rectangle(135, 267, 94, 86), Label = "", Position = new Vector2(170, 303), Pressed = false };
        weapons[5] = new Button { CollisionBox = new Rectangle(314 - 47, 300 - 43, 94, 86), Label = "", Position = new Vector2(314, 300), Pressed = false };
        weapons[6] = new Button { CollisionBox = new Rectangle(358 - 47, 423 - 43, 94, 86), Label = "", Position = new Vector2(358, 423), Pressed = false };
        weapons[7] = new Button { CollisionBox = new Rectangle(282 - 47, 511 - 43, 94, 86), Label = "", Position = new Vector2(282, 511), Pressed = false };
        weapons[8] = new Button { CollisionBox = new Rectangle(157 - 47, 488 - 43, 94, 86), Label = "", Position = new Vector2(157, 488), Pressed = false };
        weapons[9] = new Button { CollisionBox = new Rectangle(118 - 47, 386 - 43, 94, 86), Label = "", Position = new Vector2(118, 386), Pressed = false };
        weapons[10] = new Button { CollisionBox = new Rectangle(186 - 47, 297 - 43, 94, 86), Label = "", Position = new Vector2(186, 297), Pressed = false };
        //weapons[(int)state_provider.CurrentState.player.AsShip.ship_description.PrimaryWeapons[state_provider.CurrentState.player.primary_active].Type].Pressed = true;
        //weapons[(int)state_provider.CurrentState.player.AsShip.ship_description.SecondaryWeapons[state_provider.CurrentState.player.secondary_active].Type].Pressed = true;

        wtype = new Button[2];

        wtype[0] = new Button { CollisionBox = new Rectangle(142, 373, 60, 40), Label = "", Position = new Vector2(177, 398), Pressed = false };
        wtype[1] = new Button { CollisionBox = new Rectangle(267, 373, 60, 40), Label = "", Position = new Vector2(302, 398), Pressed = false };

        life_rect = new Rectangle(0, 0, (int)(life_bar.Width * 1.0f), life_bar.Height);
    }

    public override void Update(GameTime gameTime)
    {
        box.Update((float)gameTime.ElapsedGameTime.TotalSeconds * 3);

        if (state == PlayState.Pause) state_provider.Enabled = false;
        
        base.Update(gameTime);
    }

    void on_tap(Vector2 tap_position)
    {
        var t_p = tap_position.ToPoint(screen_transform);
        var play_click = false;

        switch (state)
        { 
            case PlayState.Controls:
                if (back.CollisionBox.Contains(t_p))
                {
                    state = PlayState.Pause;
                    play_click = true;
                }
                break;
            case PlayState.Pause:
                state_provider.Enabled = false;
                if (resume.CollisionBox.Contains(t_p))
                {
                    state_provider.Enabled = true;
                    state = PlayState.Playing;
                    box.StartTransition(initial_box_pos, box_dimension); //new Vector2(-300, 608), new Vector2(158, 144)
                    play_click = true;
                }
                else if (controls.CollisionBox.Contains(t_p))
                    {
                        play_click = true;
                        state = PlayState.Controls;
                    }
                    else if (quit_to_menu.CollisionBox.Contains(t_p))
                        {
                            play_click = true;
                            StateManager.SelectMenu(Game);
                        }
                break;
            case PlayState.Playing:
                if (pause_rect.Contains(t_p))
                {
                    state_provider.Enabled = false;
                    state = PlayState.Pause;
                    box.StartTransition(final_box_pos, box_dimension); //new Vector2(-300, 608), new Vector2(158, 144)
                    play_click = true;
                }
                break;
        }

        if (play_click) click.Play(AudioManager.Volume, 0.0f, 0.0f);
    }

    //private void CloseWeaponSelector()
    //{
    //    state = PlayState.Playing;
    //    for (int i = 0; i < wtype.Length; i++) wtype[i].Pressed = false;
    //    click.Play(AudioManager.Volume, 0.0f, 0.0f);

    //    state_provider.Enabled = true;
    //}

    //private void ChangeActiveWeapon(int index)
    //{
    //    int init_v = index < 5 ? 0 : 5;
    //    int fin_v = index < 5 ? 5 : weapons.Length;

    //    for (int i = init_v; i < fin_v; i++)
    //    {
    //        weapons[i].Pressed = false;
    //    }

    //    weapons[index].Pressed = true;
    //}

    static String score_string = "";
    static StringBuilder score_stringB = new StringBuilder("0");

    Color final_bar_color = new Color(18, 255, 0), life_bar_color = new Color(135,0,3);
    public override void Draw(GameTime gameTime)
    {
        sprite_batch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, screen_transform);

        switch (state)
        { 
            case PlayState.Playing:
                DrawGame();
                break;
            //case PlayState.WeaponSelection:
            //    DrawGame();
            //    DrawWeaponSelector();
            case PlayState.Pause:
                DrawGame();
                if (!box.InTransition) alpha = MathHelper.Clamp(alpha + (float)gameTime.ElapsedGameTime.TotalSeconds * 8.0f, 0.0f, 1.0f);
                DrawPauseMenu();
                break;
            case PlayState.Controls:
                DrawControls();
                break;
        }

        sprite_batch.End();

        #region Commented Code

        //fps_val = (int)(1.0 / gameTime.ElapsedGameTime.TotalSeconds);
        //sprite_batch.DrawNumericString(font_16, fps_string, fps_val, new Vector2(20, 70), Color.White, false);

        //CONTATORE DEL GC
        //timefromLastGC += (float)gameTime.ElapsedGameTime.TotalSeconds;
        //if (prevGCSize > GC.GetTotalMemory(false))
        //{            
        //    timefromLastGcPerm = (float)timefromLastGC;
        //    timefromLastGC = 0;
        //    lastGC = (float)gameTime.TotalGameTime.TotalSeconds;
        //    //s1.Remove(0, s1.Length);
        //    //s1.Append(timefromLastGC);
        //}
        //prevGCSize = GC.GetTotalMemory(false);
        //sprite_batch.DrawNumericString(arial14, null, timefromLastGcPerm, new Vector2(10, 10), Color.White, false);
        //sprite_batch.DrawNumericString(arial14, null, timefromLastGC, new Vector2(80, 10), Color.White, false);


        //if (lastmis > 1000)
        //{
        //    //s2.Remove(0, s2.Length);
        //    //s2.Append((((float)GC.GetTotalMemory(false) - lastGCsize) / lastmis));
        //    tassocrescita = (((float)GC.GetTotalMemory(false) - lastGCsize) / lastmis) * 10.0f;
        //    lastGCsize = (float)GC.GetTotalMemory(false);
        //    lastmis = 0;
        //}

        //lastmis += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
        //sprite_batch.DrawNumericString(arial14, null, tassocrescita, new Vector2(10, 30), Color.White, false);
        //sprite_batch.DrawNumericString(arial14,null, state_provider.CurrentState.player.geometry.CollisionSkin.NonCollidables.Count, 
        //  new Vector2(10, 50), Color.White, false);

        #endregion

        base.Draw(gameTime);
    }

    #region Commented Code

    //float lastmis;
    //float lastGCsize;
    //float lastGC;
    //float timefromLastGC;
    //float timefromLastGcPerm;
    //float tassocrescita;
    //long prevGCSize;
    //float gcincrate;

    #endregion

    StringBuilder s1 = new StringBuilder(), s2 = new StringBuilder();

    #region Draw Helper

    Vector2 score_dock_pos, score_pos = new Vector2(438, 788), menu_pos;
    Rectangle life_rect;
    private void DrawGame()
    {
        life_rect.Width = (int)(life_bar.Width);
        sprite_batch.Draw(life_bar, life_rect, life_bar_color);

        sprite_batch.Draw(ui_dock, Vector2.Zero, Color.White);

        sprite_batch.Draw(score_dock, score_dock_pos, Color.White);
        sprite_batch.Draw(menu_dock, menu_pos, Color.White);

        var score_val = state_provider.CurrentScore.LevelScore;
        sprite_batch.DrawNumericString(menu_f, score_string, score_val, score_pos, Color.White, true);
       
        box.Draw(sprite_batch);
    }

    //Texture2D f_weapon_circle, s_weapon_circle, yellow_glow, white_glow;
    string tap_text = "Tap to Close";
    //Vector2 tap_text_pos, f_weapon_circle_pos, s_weapon_circle_pos, half_yglow_vec;
    private Texture2D menu_dock;
    //private void DrawWeaponSelector()
    //{
    //    sprite_batch.Draw(f_weapon_circle, f_weapon_circle_pos, Color.White);
    //    sprite_batch.DrawString(menu_f, tap_text, tap_text_pos, Color.White);
    //    if (wtype[0].Pressed || wtype[1].Pressed)
    //    {
    //        sprite_batch.Draw(s_weapon_circle, s_weapon_circle_pos, Color.White);

    //        if (wtype[0].Pressed)
    //        {
    //            sprite_batch.Draw(yellow_glow, wtype[0].Position - half_yglow_vec, Color.White);

    //            for (int i = 0; i < state_provider.CurrentState.player.AsShip.ship_description.PrimaryWeapons.Count; i++)
    //            {
    //                var index = (int)state_provider.CurrentState.player.AsShip.ship_description.PrimaryWeapons[i].Type;
    //                var t = Game.Content.Load<Texture2D>("UI/WSelector/" + ships.Weapons[index].Type.ToString());
    //                if (weapons[index].Pressed)
    //                    sprite_batch.Draw(white_glow, weapons[index].Position - half_yglow_vec, Color.White);
    //                sprite_batch.Draw(t, weapons[index].Position - new Vector2(t.Width / 2.0f, t.Height / 2.0f), Color.White);
    //            }
    //        }
    //        else
    //        {
    //            sprite_batch.Draw(yellow_glow, wtype[1].Position - half_yglow_vec, Color.White);

    //            for (int i = 0; i < state_provider.CurrentState.player.AsShip.ship_description.SecondaryWeapons.Count; i++)
    //            {
    //                var index = (int)state_provider.CurrentState.player.AsShip.ship_description.SecondaryWeapons[i].Type;
    //                var t = Game.Content.Load<Texture2D>("UI/WSelector/" + ships.Weapons[index].Type.ToString());
    //                if (weapons[index].Pressed)
    //                    sprite_batch.Draw(white_glow, weapons[index].Position - half_yglow_vec, Color.White);
    //                sprite_batch.Draw(t, weapons[index].Position - new Vector2(t.Width / 2.0f, t.Height / 2.0f), Color.White);
    //            }
    //        }
    //    }
    //}

    private void DrawPauseMenu()
    {
        //var fm = title_font.MeasureString(Strings.GamePaused);
        //sprite_batch.Draw(pause_bg, new Vector2(CenterValue(480, pause_bg.Width), CenterValue(800, pause_bg.Height)), Color.White * alpha);
        //sprite_batch.DrawString(title_font, Strings.GamePaused, new Vector2(CenterValue(480, fm.X), 235) + Vector2.One * 2.0f, Color.SteelBlue * alpha);
        //sprite_batch.DrawString(title_font, Strings.GamePaused, new Vector2(CenterValue(480, fm.X), 235), Color.White * alpha);
        sprite_batch.DrawString(menu_f, resume.Label, resume.Position, Color.White * alpha);
        sprite_batch.DrawString(menu_f, controls.Label, controls.Position, Color.White * alpha);
        sprite_batch.DrawString(menu_f, quit_to_menu.Label, quit_to_menu.Position, Color.White * alpha);
    }

    private void DrawControls()
    {
        //sprite_batch.Draw(single_tap, new Vector2(85, 100), Color.White * alpha);
        //sprite_batch.DrawString(font_32, Strings.Controls_SingleTap, new Vector2(150, 120), Color.White * alpha);
        //sprite_batch.DrawString(font_16, Strings.Controls_ST_Desc_OF.Replace("\\n","\n"), new Vector2(80, 180), Color.White * alpha);
        //sprite_batch.DrawString(font_16, Strings.Controls_ST_Desc_OE.Replace("\\n", "\n"), new Vector2(80, 260), Color.White * alpha);

        //sprite_batch.Draw(double_tap, new Vector2(85, 360), Color.White * alpha);
        //sprite_batch.DrawString(font_32, Strings.Controls_DoubleTap, new Vector2(150, 370), Color.White * alpha);
        //sprite_batch.DrawString(font_16, Strings.Controls_DT_Desc_OE.Replace("\\n", "\n"), new Vector2(80, 430), Color.White * alpha);

        //sprite_batch.Draw(long_tap, new Vector2(85, 530), Color.White * alpha);
        //sprite_batch.DrawString(font_32, Strings.Controls_LongTap, new Vector2(150, 540), Color.White * alpha);
        //sprite_batch.DrawString(font_16, Strings.Controls_LT_Desc_OF.Replace("\\n", "\n"), new Vector2(80, 600), Color.White * alpha);

        //sprite_batch.DrawString(font_32, back.Label, back.Position + Vector2.One * 2.5f, Color.SteelBlue * alpha);
        //sprite_batch.DrawString(font_32, back.Label, back.Position, Color.White * alpha);
    }

    #endregion
    private float CenterValue(float screen_dim, float item_width)
    {
        return screen_dim / 2.0f - item_width / 2.0f;
    }
  }
}
